#include <../../../drivers/oprofile/cpu_buffer.h>
#include <../../../drivers/oprofile/event_buffer.h>
+#define MAX_XENOPROF_SAMPLES 16
+
static int xenoprof_start(void);
static void xenoprof_stop(void);
/* sample buffers shared with Xen */
xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
/* Shared buffer area */
-char * shared_buffer;
+char * shared_buffer = NULL;
/* Number of buffers in shared area (one per VCPU) */
int nbuf;
/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
}
+static int map_xenoprof_buffer(int max_samples)
+{
+ struct xenoprof_get_buffer get_buffer;
+ struct xenoprof_buf *buf;
+ int npages, ret, i;
+ struct vm_struct *area;
+
+ if ( shared_buffer )
+ return 0;
+
+ get_buffer.max_samples = max_samples;
+
+ if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
+ return ret;
+
+ nbuf = get_buffer.nbuf;
+ npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
+
+ area = alloc_vm_area(npages * PAGE_SIZE);
+ if (area == NULL)
+ return -ENOMEM;
+
+ if ( (ret = direct_kernel_remap_pfn_range(
+ (unsigned long)area->addr,
+ get_buffer.buf_maddr >> PAGE_SHIFT,
+ npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) {
+ vunmap(area->addr);
+ return ret;
+ }
+
+ shared_buffer = area->addr;
+ for (i=0; i< nbuf; i++) {
+ buf = (struct xenoprof_buf*)
+ &shared_buffer[i * get_buffer.bufsize];
+ BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+ xenoprof_buf[buf->vcpu_id] = buf;
+ }
+
+ return 0;
+}
+
+
static int xenoprof_setup(void)
{
int ret;
int i;
- ret = bind_virq();
- if (ret)
+ if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
+ return ret;
+
+ if ( (ret = bind_virq()) )
return ret;
if (is_primary) {
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
struct xenoprof_init init;
- struct xenoprof_buf *buf;
- int npages, ret, i;
- struct vm_struct *area;
+ int ret, i;
- init.max_samples = 16;
ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
if (!ret) {
- pgprot_t prot = __pgprot(_KERNPG_TABLE);
-
num_events = init.num_events;
is_primary = init.is_primary;
- nbuf = init.nbuf;
/* just in case - make sure we do not overflow event list
- (i.e. counter_config list) */
+ (i.e. counter_config list) */
if (num_events > OP_MAX_COUNTER)
num_events = OP_MAX_COUNTER;
- npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1;
-
- area = alloc_vm_area(npages * PAGE_SIZE);
- if (area == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = direct_kernel_remap_pfn_range(
- (unsigned long)area->addr,
- init.buf_maddr >> PAGE_SHIFT,
- npages * PAGE_SIZE, prot, DOMID_SELF);
- if (ret) {
- vunmap(area->addr);
- goto out;
- }
-
- shared_buffer = area->addr;
-
- for (i=0; i< nbuf; i++) {
- buf = (struct xenoprof_buf*)
- &shared_buffer[i * init.bufsize];
- BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
- xenoprof_buf[buf->vcpu_id] = buf;
- }
-
/* cpu_type is detected by Xen */
cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
active_defined = 0;
}
- out:
printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
"is_primary %d\n", ret, num_events, is_primary);
return ret;
int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_init xenoprof_init;
- int is_primary, num_events;
- struct domain *d = current->domain;
int ret;
if ( copy_from_guest(&xenoprof_init, arg, 1) )
return -EFAULT;
- ret = nmi_init(&num_events,
- &is_primary,
- xenoprof_init.cpu_type);
- if ( ret < 0 )
- goto err;
+ if ( (ret = nmi_init(&xenoprof_init.num_events,
+ &xenoprof_init.is_primary,
+ xenoprof_init.cpu_type)) )
+ return ret;
- if ( is_primary )
+ if ( copy_to_guest(arg, &xenoprof_init, 1) )
+ return -EFAULT;
+
+ if ( xenoprof_init.is_primary )
primary_profiler = current->domain;
+ return 0;
+}
+
+int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
+{
+ struct xenoprof_get_buffer xenoprof_get_buffer;
+ struct domain *d = current->domain;
+ int ret;
+
+ if ( copy_from_guest(&xenoprof_get_buffer, arg, 1) )
+ return -EFAULT;
+
/*
- * We allocate xenoprof struct and buffers only at first time xenoprof_init
+ * We allocate xenoprof struct and buffers only at first time xenoprof_get_buffer
* is called. Memory is then kept until domain is destroyed.
*/
if ( (d->xenoprof == NULL) &&
- ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) )
- goto err;
+ ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) )
+ return ret;
xenoprof_reset_buf(d);
d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
d->xenoprof->domain_ready = 0;
- d->xenoprof->is_primary = is_primary;
-
- xenoprof_init.is_primary = is_primary;
- xenoprof_init.num_events = num_events;
- xenoprof_init.nbuf = d->xenoprof->nbuf;
- xenoprof_init.bufsize = d->xenoprof->bufsize;
- xenoprof_init.buf_maddr = __pa(d->xenoprof->rawbuf);
-
- if ( copy_to_guest(arg, &xenoprof_init, 1) )
- {
- ret = -EFAULT;
- goto err;
- }
+ if ( primary_profiler == current->domain )
+ d->xenoprof->is_primary = 1;
+ else
+ d->xenoprof->is_primary = 0;
+
+ xenoprof_get_buffer.nbuf = d->xenoprof->nbuf;
+ xenoprof_get_buffer.bufsize = d->xenoprof->bufsize;
+ xenoprof_get_buffer.buf_maddr = __pa(d->xenoprof->rawbuf);
- return ret;
+ if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) )
+ return -EFAULT;
- err:
- if ( primary_profiler == current->domain )
- primary_profiler = NULL;
- return ret;
+ return 0;
}
#define PRIV_OP(op) ( (op == XENOPROF_set_active) \
ret = xenoprof_op_init(arg);
break;
+ case XENOPROF_get_buffer:
+ ret = xenoprof_op_get_buffer(arg);
+ break;
+
case XENOPROF_reset_active_list:
{
reset_active_list();
#define XENOPROF_disable_virq 11
#define XENOPROF_release_counters 12
#define XENOPROF_shutdown 13
+#define XENOPROF_get_buffer 14
+#define XENOPROF_last_op 14
#define MAX_OPROF_EVENTS 32
#define MAX_OPROF_DOMAINS 25
DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
struct xenoprof_init {
- int32_t max_samples;
int32_t num_events;
int32_t is_primary;
- int32_t nbuf;
- int32_t bufsize;
- uint64_t buf_maddr;
char cpu_type[XENOPROF_CPU_TYPE_SIZE];
};
typedef struct xenoprof_init xenoprof_init_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
+struct xenoprof_get_buffer {
+ int32_t max_samples;
+ int32_t nbuf;
+ int32_t bufsize;
+ uint64_t buf_maddr;
+};
+typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
+
struct xenoprof_counter {
uint32_t ind;
uint64_t count;